﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Net.Sockets;

namespace Rung.EBook.WebSiteAnalizer.Driver
{
    public static class HttpHelper
    {
        private static WebProxy mWebProxy;

        /// <summary>
        /// 获取指定远程网页内容
        /// </summary>
        public static string Get(string url, Encoding encodingType, HttpMethod method)
        {
            var internetIp = from ip in Dns.GetHostEntry(Dns.GetHostName()).AddressList
                             where ip.ToString().StartsWith("192.168")
                             select ip;

            if (internetIp != null)
                return Get(url, encodingType, null, method);
            else
                return Get(url, encodingType, GetHnasProxy(), method);
        }

        /// <summary>
        /// 获取指定远程网页内容
        /// </summary>
        public static string Get(string url, Encoding encodingType)
        {
            var internetIp = from ip in Dns.GetHostEntry(Dns.GetHostName()).AddressList
                             where ip.ToString().StartsWith("192.168")
                             select ip;

            if (internetIp != null)
                return Get(url, encodingType, null, HttpMethod.Get);
            else
                return Get(url, encodingType, GetHnasProxy(), HttpMethod.Get);
        }

        /// <summary>
        /// 获取指定远程网页内容
        /// </summary>
        /// <param name="strUrl">所要查找的远程网页地址</param>
        /// <param name="timeout">超时时长设置，一般设置为8000</param>
        /// <param name="encodingType">编码方式</param>
        public static string Get(string url, Encoding encodingType, WebProxy proxy, HttpMethod method)
        {
            return Get(url, 80000, true, encodingType, proxy, method);
        }

        /// <summary>
        /// 获取指定远程网页内容
        /// </summary>
        /// <param name="strUrl">所要查找的远程网页地址</param>
        /// <param name="timeout">超时时长设置，一般设置为8000</param>
        /// <param name="enterType">是否输出换行符，false不输出，true输出文本框换行</param>
        /// <param name="encodingType">编码方式</param>
        /// <param name="proxy">代理</param>
        /// <param name="method">参数传递方式（默认为GET）。</param>
        /// <returns></returns>
        public static string Get(string url, int timeout, bool enterType, Encoding encodingType, WebProxy proxy, HttpMethod method)
        {
            try
            {
                HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url);

                req.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
                req.Headers[HttpRequestHeader.AcceptCharset] = "GBK,utf-8;q=0.7,*;q=0.3";
                req.Headers[HttpRequestHeader.AcceptEncoding] = "gzip,deflate,sdch";
                req.Headers.Add(HttpRequestHeader.AcceptLanguage, "zh-CN,zh;q=0.8");
                req.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore);
                req.Referer = "http://v.book.ifeng.com/read/book/chapter_info/13111/1302838.htm";
                req.UserAgent = "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.83 Safari/535.11 QIHU 360EE";
                req.KeepAlive = true;
                req.Timeout = timeout;
                req.ContentType = "text/html";
                req.Method = method == HttpMethod.Post ? "POST" : "GET";

                if (proxy != null) req.Proxy = proxy;

                using (WebResponse rep = req.GetResponse())
                {
                    System.IO.Stream stream = null;
                    try
                    {
                        //判断网页是否经过压缩，选择接受响应流的解析器（GZipStream / Stream）。
                        string encoding = rep.Headers[HttpResponseHeader.ContentEncoding];
                        switch (encoding)
                        {
                            case "gzip":
                                stream = new System.IO.Compression.GZipStream(rep.GetResponseStream(), System.IO.Compression.CompressionMode.Decompress);
                                break;
                            default:
                                stream = rep.GetResponseStream();
                                break;
                        }

                        // 获取 HTML 文档
                        using (StreamReader reader = new StreamReader(stream, encodingType))
                        {
                            StringBuilder sb = new StringBuilder();
                            while (-1 != reader.Peek() || sb.Length < rep.ContentLength)// 加入 WebResponse.ContentLength 长度的验证，否则常常发生 html 只获取到部分的问题。
                            {
                                sb.Append(reader.ReadLine());
                                if (enterType == true)
                                {
                                    sb.Append("\r\n");
                                }
                            }
                            return sb.ToString();
                        }
                    }
                    catch { throw; }
                    finally
                    {
                        if (null != stream)
                        stream.Close();
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public static string GetByTcp(string url)
        {
            string strHTML = "";//用来保存获得的HTML代码

            Uri uri = new Uri(url);
            TcpClient clientSocket = HttpHelper.ConnectSocket(uri.Host, uri.Port);

            //clientSocket.Connect(uri.Host, uri.Port);
            StringBuilder RequestHeaders = new StringBuilder();//用来保存HTML协议头部信息
            RequestHeaders.AppendFormat("{0} {1} HTTP/1.1\r\n", "GET", uri.PathAndQuery);
            RequestHeaders.AppendFormat("Connection:close\r\n");
            RequestHeaders.AppendFormat("Host:{0}\r\n", uri.Host);
            RequestHeaders.AppendFormat("Accept:*/*\r\n");
            RequestHeaders.AppendFormat("Accept-Language:zh-cn\r\n");
            RequestHeaders.AppendFormat("User-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)\r\n\r\n");
            Encoding encoding = Encoding.Default;
            byte[] request = encoding.GetBytes(RequestHeaders.ToString());
            clientSocket.Client.Send(request);
            //获取要保存的网络流
            Stream readStream = clientSocket.GetStream();
            StreamReader sr = new StreamReader(readStream, Encoding.Default);
            strHTML = sr.ReadToEnd();


            readStream.Close();
            clientSocket.Close();

            return strHTML;

        }

        private static TcpClient ConnectSocket(string server, int port)
        {
            TcpClient tcp = null;
            IPHostEntry hostEntry = null;

            // Get host related information.
            hostEntry = Dns.GetHostEntry(server);

            // Loop through the AddressList to obtain the supported AddressFamily. This is to avoid
            // an exception that occurs when the host IP Address is not compatible with the address family
            // (typical in the IPv6 case).
            foreach (IPAddress address in hostEntry.AddressList)
            {
                IPEndPoint ipe = new IPEndPoint(address, port);
                TcpClient tempSocket = new TcpClient(ipe.AddressFamily);

                tempSocket.Connect(ipe);

                if (tempSocket.Connected)
                {
                    tcp = tempSocket;
                    break;
                }
                else
                {
                    continue;
                }
            }
            return tcp;
        }

        /// <summary>
        /// 获取本机默认的票据
        /// </summary>
        public static WebProxy GetHnasProxy()
        {
            if (HttpHelper.mWebProxy == null)
            {
                HttpHelper.mWebProxy = new WebProxy("isasrvhk01", 80);
                HttpHelper.mWebProxy.BypassProxyOnLocal = true;
                HttpHelper.mWebProxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
            }
            return HttpHelper.mWebProxy;
        }
    }

    /// <summary>
    /// 参数传输方式（POST、GET）。
    /// </summary>
    public enum HttpMethod
    {
        Get,
        Post
    }
}
